home *** CD-ROM | disk | FTP | other *** search
/ APDL Other Worlds / APDL Other Worlds Collection.iso / SF3000 / Extras / CBlibrary / c / Pal256 < prev    next >
Encoding:
Text File  |  2003-10-16  |  11.4 KB  |  327 lines

  1. /*
  2.  * CBLibrary - Pal256
  3.  * Copyright (C) 2003  Chris Bazley
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2.1 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19.  
  20. /* 256 colour selection dialogue */
  21.  
  22. #include "Pal256.h"
  23.  
  24. /* ANSI library files */
  25. #include <stdlib.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28.  
  29. /* RISC OS library files */
  30. #include "kernel.h"
  31. #include "swis.h"
  32. #include "wimp.h"
  33. #include "wimplib.h"
  34. #include "toolbox.h"
  35. #include "event.h"
  36. #include "window.h"
  37. #include "gadgets.h"
  38.  
  39. /* Other headers */
  40. #include "err.h"
  41. #include "msgtrans.h"
  42. #include "Macros.h"
  43.  
  44. /* Gadgets */
  45. #define PAL256_CANCEL  0x100
  46. #define PAL256_OK      0x101
  47. #define PAL256_COLOUR  0x105
  48. #define PAL256_PALETTE 0x104
  49.  
  50. /* Bounding box of area to draw colours */
  51. #define COLOURS_XORIG  28
  52. #define COLOURS_YORIG  104
  53. #define COLOURS_WIDTH  576
  54. #define COLOURS_HEIGHT 576
  55. #define WIN_HEIGHT     708
  56.  
  57. #ifndef NDEBUG
  58. #define OSPLOT(c,x,y) { \
  59.     char string[255]; \
  60.     sprintf(string, "report OS_Plot action:%d x coord:%d y coord:%d", c, x, y); \
  61.     _kernel_oscli(string); \
  62.   } \
  63.   RE(_swix(OS_Plot, _INR(0,2), c, x, y))
  64. #else
  65. #define OSPLOT(c,x,y)  RE(_swix(OS_Plot, _INR(0,2), c, x, y))
  66. #endif
  67.  
  68. typedef struct _Pal256Data
  69. {
  70.   ObjectId window_id; /* editing window */
  71.   char orig_colnum; /* as specified by client */
  72.   char current_colnum; /* as displayed in dialogue */
  73.   WimpCaret caretstore;
  74. } Pal256Data;
  75.  
  76. extern int palette[256];
  77. extern _kernel_oserror shared_err_block;
  78.  
  79. /* ----------------------------------------------------------------------- */
  80. /*                       Function prototypes                               */
  81.  
  82. static ToolboxEventHandler _Pal256_buttonhandler, _Pal256_deleted;
  83. static WimpEventHandler _Pal256_redrawhandler, _Pal256_clickhandler;
  84. static _kernel_oserror *_Pal256_disp_colour(Pal256Data *pal_data, char colour_number);
  85.  
  86. /* ----------------------------------------------------------------------- */
  87. /*                         Public functions                                */
  88.  
  89. _kernel_oserror *Pal256_initialise(ObjectId object)
  90. {
  91.   /* Create associated data block */
  92.   Pal256Data *pal_data;
  93.   _kernel_oserror *err;
  94.  
  95.   pal_data = malloc(sizeof(Pal256Data));
  96.   if(pal_data == NULL) {
  97.     WRITE_GERR(shared_err_block, "NoMem");
  98.     return &shared_err_block; /* failed */
  99.   }
  100.   err = toolbox_set_client_handle(0, object, pal_data);
  101.   if(err != NULL) goto err_exit;
  102.  
  103.   pal_data->window_id = object;
  104.   pal_data->orig_colnum = 0;
  105.   pal_data->current_colnum = 0;
  106.  
  107.   /* Install handlers */
  108.   err = event_register_wimp_handler(object, Wimp_ERedrawWindow, _Pal256_redrawhandler, pal_data);
  109.   if(err != NULL) goto err_exit;
  110.  
  111.   err = event_register_wimp_handler(object, Wimp_EMouseClick, _Pal256_clickhandler, pal_data);
  112.   if(err != NULL) goto err_exit;
  113.  
  114.   err = event_register_toolbox_handler(object, ActionButton_Selected, _Pal256_buttonhandler, pal_data);
  115.   if(err != NULL) goto err_exit;
  116.  
  117.   err = event_register_toolbox_handler(object, Toolbox_ObjectDeleted, _Pal256_deleted, pal_data);
  118.   if(err != NULL) goto err_exit;
  119.  
  120.   return NULL; /* success */
  121.  
  122.   err_exit:
  123.     free(pal_data);
  124.     return err; /* failed */
  125. }
  126.  
  127. /* ----------------------------------------------------------------------- */
  128.  
  129. _kernel_oserror *Pal256_set_colour(ObjectId object, char colour_number)
  130. {
  131.   /* Set the currently selected colour */
  132.   Pal256Data *pal_data;
  133.  
  134.   THROW(toolbox_get_client_handle(0, object, (void **)&pal_data));
  135.   pal_data->orig_colnum = colour_number; /* remember client-specified colour, incase restored by ADJUST-click on Cancel */
  136.   return _Pal256_disp_colour(pal_data, colour_number);
  137. }
  138.  
  139. /* ----------------------------------------------------------------------- */
  140. /*                         Private functions                               */
  141.  
  142. static _kernel_oserror *_Pal256_disp_colour(Pal256Data *pal_data, char colour_number)
  143. {
  144.   /* Change the displayed colour */
  145.   char validation[16];
  146.  
  147.   pal_data->current_colnum = colour_number;
  148.   sprintf(validation,"r2;c/%X", (palette[colour_number] & 0xffffff00) >> 8);
  149.   return button_set_validation(0, pal_data->window_id, PAL256_COLOUR, validation);
  150.  
  151. }
  152.  
  153. static int _Pal256_buttonhandler(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  154. {
  155.   Pal256Data *pal_data = (Pal256Data *)handle;
  156.   Pal256ColourSelectedEvent warn_client;
  157.   NOT_USED(event_code)
  158.  
  159.   switch(id_block->self_component) {
  160.     case PAL256_CANCEL:
  161.       if(FLAG_SET(event->hdr.flags, ActionButton_Selected_Adjust)) {
  162.         /* restore default colour as specified by client */
  163.         RE(_Pal256_disp_colour(pal_data, pal_data->orig_colnum))
  164.       }
  165.       break;
  166.  
  167.     case PAL256_OK:
  168.       /* Raise event to tell client of colour selection */
  169.       warn_client.hdr.size = sizeof(Pal256ColourSelectedEvent);
  170.       warn_client.hdr.event_code = Pal256_ColourSelected;
  171.       warn_client.hdr.flags = 0;
  172.       warn_client.colour_number = pal_data->current_colnum;
  173.       RE(toolbox_raise_toolbox_event(0, id_block->self_id, -1, (ToolboxEvent *)&warn_client))
  174.       pal_data->orig_colnum = pal_data->current_colnum; /* this becomes the new default colour */
  175.  
  176.     default:
  177.       return 0; /* not interested in this button */
  178.   }
  179.   return 1; /* claim event */
  180. }
  181.  
  182. /* ----------------------------------------------------------------------- */
  183.  
  184. static int _Pal256_clickhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle)
  185. {
  186.   /* In order that the pseudo-transient dbox mechanism can work
  187.      we pass mouse click events on rather than claiming them */
  188.   WimpMouseClickEvent *wmce = (WimpMouseClickEvent *)event;
  189.   NOT_USED(event_code)
  190.  
  191.   if(wmce->buttons != Wimp_MouseButtonSelect || id_block->self_component != PAL256_PALETTE)
  192.     return 0; /* event not handled */
  193.  
  194.   /* Calculate palette origin in screen coordinates */
  195.   WimpGetWindowStateBlock winstate;
  196.   E_RETV(window_get_wimp_handle(0, id_block->self_id, &(winstate.window_handle)), 0)
  197.   E_RETV(wimp_get_window_state(&winstate), 0)
  198.   int row = wmce->mouse_y - (winstate.visible_area.ymax - winstate.yscroll - WIN_HEIGHT + COLOURS_YORIG);
  199.   if(row < 0 || row >= COLOURS_HEIGHT)
  200.     return 0; /* pass event on */
  201.   row /= (COLOURS_HEIGHT/16);
  202.   int col = wmce->mouse_x - (winstate.visible_area.xmin - winstate.xscroll + COLOURS_XORIG);
  203.   if(col < 0 || col >= COLOURS_WIDTH)
  204.     return 0; /* pass event on */
  205.   col /= (COLOURS_WIDTH/16);
  206.  
  207.   /* Select colour */
  208.   RE(_Pal256_disp_colour((Pal256Data *)handle,  col + (15-row) * 16))
  209.  
  210.   return 0; /* pass event on */
  211. }
  212.  
  213. /* ----------------------------------------------------------------------- */
  214.  
  215. static int _Pal256_redrawhandler(int event_code, WimpPollBlock *event, IdBlock *id_block, void *handle)
  216. {
  217.   /* Custom redraw for colour palette */
  218.   NOT_USED(event_code)
  219.   NOT_USED(event)
  220.   NOT_USED(handle)
  221.  
  222.   WimpRedrawWindowBlock block;
  223.   E_RETV(window_get_wimp_handle(0, id_block->self_id, &block.window_handle), 1)
  224.   int more;
  225.   E_RETV(wimp_redraw_window(&block, &more), 1)
  226.  
  227.   /* Calculate palette origin in screen coordinates */
  228.   int colsleft_scrx = block.visible_area.xmin - block.xscroll + COLOURS_XORIG;
  229.   int colsbot_scry = block.visible_area.ymax - block.yscroll - WIN_HEIGHT + COLOURS_YORIG;
  230.   /* N.B. Whilst it would be more logical to have the origin at the top left, this cannot be calculated accurately enough to avoid OS-to-pixel coordinate rounding errors without using the current y eigen factor */
  231.  
  232. #ifndef NDEBUG
  233.   {
  234.     char string[255];
  235.     sprintf(string, "report palette origin left:%d bottom:%d", colsleft_scrx, colsbot_scry);
  236.     _kernel_oscli(string);
  237.   }
  238. #endif
  239.  
  240.   while (more) {
  241. #ifndef NDEBUG
  242.     {
  243.       char string[255];
  244.       sprintf(string, "report redraw rectangle xmin:%d ymin:%d xmax:%d ymax:%d", block.redraw_area.xmin, block.redraw_area.ymin, block.redraw_area.xmax, block.redraw_area.ymax);
  245.       _kernel_oscli(string);
  246.     }
  247. #endif
  248.  
  249.     /* Clip redraw area to palette area */
  250.     if(block.redraw_area.xmin < colsleft_scrx)
  251.       block.redraw_area.xmin = colsleft_scrx;
  252.     if(block.redraw_area.xmax > colsleft_scrx + COLOURS_WIDTH)
  253.       block.redraw_area.xmax = colsleft_scrx + COLOURS_WIDTH;
  254.     if(block.redraw_area.ymax > colsbot_scry + COLOURS_HEIGHT)
  255.       block.redraw_area.ymax = colsbot_scry + COLOURS_HEIGHT;
  256.     if(block.redraw_area.ymin < colsbot_scry)
  257.       block.redraw_area.ymin = colsbot_scry;
  258. #ifndef NDEBUG
  259.     {
  260.       char string[255];
  261.       sprintf(string, "report clipped redraw rectangle xmin:%d ymin:%d xmax:%d ymax:%d", block.redraw_area.xmin, block.redraw_area.ymin, block.redraw_area.xmax, block.redraw_area.ymax);
  262.       _kernel_oscli(string);
  263.     }
  264. #endif
  265.  
  266.     /* Calculate rows and columns to draw */
  267.     int max_col = block.redraw_area.xmax - colsleft_scrx;
  268.     if(max_col >= 0) {
  269.       max_col /= COLOURS_WIDTH/16;
  270.       if((block.redraw_area.xmax - colsleft_scrx) % (COLOURS_WIDTH/16) == 0)
  271.         max_col--; /* redraw_area.xmax is exclusive, so don't draw column that coincides exactly with it */
  272.   
  273.       int row = block.redraw_area.ymax - colsbot_scry;
  274.       if(row >= 0) {
  275.         row /= COLOURS_HEIGHT/16;
  276.         if((block.redraw_area.ymax - colsbot_scry) % (COLOURS_HEIGHT/16) == 0)
  277.           row--; /* redraw_area.ymax is exclusive, so don't draw row that coincides exactly with it */
  278.  
  279.         int min_col = (block.redraw_area.xmin - colsleft_scrx)/(COLOURS_WIDTH/16);
  280.         int min_row = (block.redraw_area.ymin - colsbot_scry)/(COLOURS_HEIGHT/16);
  281. #ifndef NDEBUG
  282.         {
  283.           char string[255];
  284.           sprintf(string, "report start row:%d end row:%d start col:%d end col:%d", row, min_row, min_col, max_col);
  285.           _kernel_oscli(string);
  286.         }
  287. #endif    
  288.   
  289.         /* Draw colour squares */
  290.         for(; row >= min_row; row--) {
  291.           for(int col = min_col; col <= max_col; col++) {
  292.             RE(_swix(ColourTrans_SetGCOL, _IN(0)|_INR(3,4),
  293.               palette[col + (15 - row) * 16], /* Set colour */
  294.               0, /* No flags */
  295.               0 /* Replace colour on screen */
  296.             ))
  297.     
  298.             /* Move, absolute */
  299.             OSPLOT(4, colsleft_scrx + col * (COLOURS_WIDTH/16), colsbot_scry + row * (COLOURS_HEIGHT/16))
  300.     
  301.             /* Plot rectangle, relative */
  302.             OSPLOT(96+1, COLOURS_WIDTH/16 - 1, COLOURS_HEIGHT/16 - 1)
  303.           } /* next col */
  304.         } /* next row */
  305.       }
  306.     }
  307.     E_RETV(wimp_get_rectangle(&block, &more), 1)
  308.   }
  309.   return 1; /* claim event */
  310. }
  311.  
  312. /* ----------------------------------------------------------------------- */
  313.  
  314. static int _Pal256_deleted(int event_code, ToolboxEvent *event, IdBlock *id_block, void *handle)
  315. {
  316.   /* Remove handlers */
  317.   NOT_USED(event_code)
  318.   NOT_USED(event)
  319.  
  320.   RE(event_deregister_toolbox_handler(id_block->self_id, ActionButton_Selected, _Pal256_buttonhandler, handle))
  321.   RE(event_deregister_toolbox_handler(id_block->self_id, Toolbox_ObjectDeleted, _Pal256_deleted, handle))
  322.   RE(event_deregister_wimp_handler(id_block->self_id, Wimp_ERedrawWindow, _Pal256_redrawhandler, handle))
  323.   RE(event_deregister_wimp_handler(id_block->self_id, Wimp_EMouseClick, _Pal256_clickhandler, handle))
  324.  
  325.   return 1; /* claim event */
  326. }
  327.